#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include "ThreadPool.h"
#include "PoolJob.h"

#include <Winsock.h>

static BOOL	__stdcall ctrlHandler(DWORD ctrlEvent);

int main(int argc, char *argv[])
{

	WSADATA		wsaData;
	SOCKET		servSock, clientSock;
	
	SOCKADDR_IN		servAddr, clientAddr;

	int		port = 9816;
	int		clientAddrLen;
	int		ret;

	BOOL	bReuseAddr = TRUE;

	CThreadPool		&pool = CThreadPool::GetInstance();


	// Register a console control handler
	if( !SetConsoleCtrlHandler(ctrlHandler, TRUE))
		fprintf(stderr, "Error setting event handler\n");

	// initialize a thread pool
	pool.initPool(2);


	ret = WSAStartup(MAKEWORD(2,2), &wsaData);
	if( ret != 0 ) {
		fprintf(stderr, "WSAStartup error\n");
		exit(1);
	}

	servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if( SOCKET_ERROR == servSock ) {
		fprintf(stderr, "socket creation error\n");
		exit(1);
	}

	ret = setsockopt(servSock, SOL_SOCKET, SO_REUSEADDR, (char *)&bReuseAddr, sizeof(BOOL));
	if( SOCKET_ERROR == ret ) {
		fprintf(stderr, "setsockopt error\n");
		exit(1);
	}

	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	servAddr.sin_port = htons(port);

	bind(servSock, (SOCKADDR *)&servAddr, sizeof(servAddr));

	listen(servSock, 5);

	while(1) {
		printf("Waiting for client....\n");
		clientAddrLen = sizeof(clientAddr);
		clientSock = accept(servSock, (SOCKADDR *)&clientAddr, &clientAddrLen);
		if( INVALID_SOCKET == clientSock) {
			fprintf(stderr, "accept error\n");
			break;
		}

		printf("Connecting!\n\n");

		CPoolJobTest *job = new CPoolJobTest[1];

		// assign job to any thread in thr thread pool
		job->SetClientSock(clientSock);
		pool.registJob(job);
	}

	closesocket(servSock);

	pool.destroyPool();

	WSACleanup();
}

		
BOOL __stdcall ctrlHandler(DWORD ctrlEvent)
{
	switch(ctrlEvent) {
		case CTRL_C_EVENT:
			printf("Ctrl-C received. Leaving in 2 sec.\n");
			CThreadPool::GetInstance().destroyPool();
			Sleep(2000);
			exit(0);
		case CTRL_CLOSE_EVENT:
			printf("close event reveived\n");
			CThreadPool::GetInstance().destroyPool();
			Sleep(2000);
			exit(0);
		default:
			return TRUE;
	}
}
